﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Luna;
using System.IO;
using VulnDB.Action.DataCollectors.Actions;

namespace VulnDB.Action.DataCollectors {

	public class HtmlTag {

		public HtmlTag(string tag, string htmlText) {
			this.HtmlText = htmlText;
			this.Tag = tag;
			parse();
		}

		public string HtmlText { get; private set; }

		public string Tag { get; private set; }

		public string ChildrenHtml { get; private set; }

		public string AttributeHtml { get; private set; }

		protected void parse() {	
			string pattern = "<{0}([^>]*)>".format(Tag);
			string endPatter = "</{0}>".format(Tag);
			Regex tagReg = new Regex(pattern, RegexOptions.Multiline | RegexOptions.IgnoreCase);
			Match ep = Regex.Match(HtmlText, endPatter, RegexOptions.IgnoreCase | RegexOptions.Multiline);
			Match m = tagReg.Match(HtmlText);
			if (m.Success && ep.Success) {
				AttributeHtml = m.Groups[1].Value;
				ChildrenHtml = HtmlText.Substring(m.Value.Length, ep.Index - m.Value.Length);
				if (!string.IsNullOrWhiteSpace(AttributeHtml))
					parseAttributes();
			}
		}

		public IEnumerable<T> getChildTag<T>(string tag) where T: HtmlTag {
			Match sR = Regex.Match(ChildrenHtml, "<{0}([^>]*)>".format(tag), RegexOptions.Multiline | RegexOptions.IgnoreCase);
			Match eR = Regex.Match(ChildrenHtml, "</{0}>".format(tag), RegexOptions.Multiline | RegexOptions.IgnoreCase);

			while (sR.Success && eR.Success) {
				String row = ChildrenHtml.Substring(sR.Index, eR.Index + eR.Length - sR.Index);
				yield return (T) Activator.CreateInstance(typeof(T), row);
				sR = sR.NextMatch();
				eR = eR.NextMatch();
			}
		}

		protected void parseAttributes() {
		}

		public string getAttributte(string attribName) {
			Regex aReg = new Regex("{0}=\"(.*)\"".format(attribName), RegexOptions.IgnoreCase);
			Match m = aReg.Match(AttributeHtml);
			if (m.Success)
				return m.Groups[1].Value;
			return string.Empty;
		}
	}

	public class HtmlTable : HtmlTag {

		private List<HtmlTableRow> rows;

		public HtmlTable(string  htmlText): base("table", htmlText)  {
		}

		public IEnumerable<HtmlTableRow> getRows() {
			return getChildTag<HtmlTableRow>("tr");
		}

		public List<HtmlTableRow> Rows {
			get { return rows != null ? rows : rows = new List<HtmlTableRow>(getRows()); }
		}
	}

	public class HtmlTableRow : HtmlTag  {

		private List<HtmlTableColumn> columsn;

		public HtmlTableRow(string htmlText)
			: base("tr", htmlText) {
		}

		public IEnumerable<HtmlTableColumn> getColumns() {
			return getChildTag<HtmlTableColumn>("td");
		}

		public List<HtmlTableColumn> Columns {
			get { return columsn != null ? columsn : columsn = new List<HtmlTableColumn>(getColumns()); }
		}
	}

	public class HtmlTableColumn : HtmlTag {

		public HtmlTableColumn(string htmlText)
			: base("td", htmlText) {
		}

	}

	public class TestHtmlTable {

		public void testHtmlTable() {
			string data = string.Empty;
			using (var f = new StreamReader("test-data2.htm"))
				data = f.ReadToEnd();
			int idx = data.IndexOf("<table class=\"test-results\">");
			if (idx > 0) {
				int eidx = data.IndexOf("</table>", idx);
				data = data.Substring(idx, eidx + "</table>".Length - idx + 1);
				//HtmlTable table = new HtmlTable(data);
				//List<HtmlTableRow> rows = new List<HtmlTableRow>(table.getRows());
				List<TestSuiteEntry> entries = new List<TestSuiteEntry>();
				parseReturnHtml(0, data, entries);
			}	
		}

		private void parseReturnHtml(int page, string data, List<TestSuiteEntry> result) {
			HtmlTable table = new HtmlTable(data);

			for (int i = 2; i < table.Rows.Count - 1; i++) {
				HtmlTableRow tr = table.Rows[i];
				try {
					TestSuiteEntry entry = new TestSuiteEntry();
					entry.Result = tr.getAttributte("class").convertTo<TestSuiteEntryResult>(TestSuiteEntryResult.NotSpecify);
					entry.SubmissionDate = tr.Columns[0].ChildrenHtml.convertTo<DateTime>(DateTime.MinValue);
					entry.ID = extractNumber(tr.Columns[1].ChildrenHtml);
					entry.TestCaseID = extractNumber(tr.Columns[2].ChildrenHtml);
					entry.Branch = tr.Columns[5].ChildrenHtml;
					result.Add(entry);
				}
				catch (Exception) {
					
				}
			}
		}

		private int extractNumber(string text) {
			Match m = Regex.Match(text, "\\d+");
			if (m.Success)
				return m.Value.toInt();
			return 0;
		}
	}
}
